nodejs开发中的一个持久层orm

最近在做一个项目,没有后台小哥来提供接口,无奈之下就只能自己动手丰衣足食了……看这篇文章可能需要大家了解一些数据库的知识~
技术选型用的是express(SSR),数据库用的是Mysql,orm选的是sequelize, GitHub上大概1W+的star(其实选型时考虑过bookshelf + knex,但是我真的不太喜欢他家的文档……一开始看得我满脸问号,也可能是我英文不太好啦啊哈哈)

这次主要就是介绍一下sequelize这个orm

ORM:对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),用于实现面向对象编程语言里不同类型系统的数据之间的转换。通俗一点,就是 在编程中,把面向对象的概念跟数据库中表的概念对应起来,比如说,我定义了一个object,那就对应着一张表,这个对象的实例,就对应着表中的一条记录。

我这次开发用的是MVC的开发方式,把所有和数据有关的持久层操作放到model中去映射数据库中的表,目录结构中的router处理逻辑,模板引擎用的是阿里开源的Xtemplate,讲真,这个模板引擎用习惯了还是蛮好用的……😄贴上GitHub地址:Xtemplate

sequelize应该是有中文文档的,大家可以再找一下;
sequelize算是一个比较良心的orm了,自带连接池,支持Promise写法,支持Mysql、mssql、postgrasQL、SQLite主流的关系型数据库,除了Oracle都支持,如果大家需要支持Oracle的话建议考虑knex + bookshelf或是typeorm都是比较好的选择。是否可以连接多个数据源这个我暂时还没有查资料得到结果,但是看它的结构和用法应该是支持的。

sequelize的操作是在DML的基础上进行的,也就是说我们需要在已有库上进行操作,它所支持的是DDL的操作(也就是我们最常见的增删改查的操作)同时也支持事务、视图、自定义SQL和迁移,我这次的项目也就能用到DDL的操作,所以其他的就暂且不提,把最常用的几个功能来介绍一下:

npm i sequelize --save

建表

const Sequelize = require("Sequelize")
const Op = Sequelize.Op;
//假设我要建一个test表,里面含有firstName字段和lastName字段
const test = sequelize.define('test', {
    firstName: {
        type: Sequelize.STRING
    },
    lastName: {
        type: Sequelize.STRING
    }
});
//注意:此时建表成功后你查看数据库时,会发现我们刚建成功的表名叫tests,用sequelize建的表名实际上都会在你代码里表名后面加一个s,但是我们平时用的时候不需要去加s

//如果是在已有表的基础上去进行操作,那么就需要声明表的数据结构,参考上面的建表操作,如果是已有表就不会重复建表

//此方法会先查询,如果查询到有此条数据相同的就不会新增,返回created:false,得到查询结果
test.findOrCreate({where: {firstName: 'star',lastName: '37589'}})
  .spread((test, created) => {
    console.log(test.get({
      plain: true
    }))
    console.log('啦啦啦'+created)
  })
  //第二种创建方法是直接创建,没有查询动作
  test.create({
    firstName: 'star',
    lastName: '37589'
  }).then(function(result){
        console.log('inserted ok');
  }).catch(function(err){
        console.log('inserted error');
  });

一般而言我们不会去删数据库中的数据,会加一个status来控制数据的状态,但是这里还是介绍一下删除操作

//模糊查询的相关知识请自行查资料~
  test.destroy({
    where:{
        firstName:{
          [Op.like]:'%66%'//模糊查询
        }
    }
  }).then(function(result){
          console.log('destroy success');
          console.log(result);  //会返回操作了多少条数据
  });

//查有无数种方式来实现,这里就讲几种主流的
//第一种:
  test.findOne({ where: {firstName: 'sdepold'} }).then(item => {
    // project will be the first entry of the Projects table with the title 'aProject' || null
    console.log('这是查询得到的'+ item.firstName)
  })
//第二种
test.findById(123).then(item=> {
if(item){
    console.log(item)
    //如果有id为123的row,会返回查找到的结果
  } else {
    console.log("没有找到结果")
  }
})
//第三种
test.findOne({
  where: {firstName: 'mary'},
  attributes: ['id', ['name', 'title']]
}).then(item => {
  //
})
//第四种,这一种主要是针对分页处理数据的情况,非常方便
test
  .findAndCountAll({
     where: {
        title: {
          [Op.like]: 'foo%'
        }
     },
     offset: 10,    //数据偏移量
     limit: 20      //每次查出的条数
  })
  .then(result => {
    console.log(result.count);
    console.log(result.rows);
  });
//第五种
test.findAll().then(item => {
  // 会返回所有数据
})
查找还有许多用法,其他的还请大家自己去找吧~

改(更新)

  test.update({
    firstName:'12'
  },{
    where:{
      firstName:'sdepold'
    }
}).then(function(result){
      console.log('updated success');
      console.log(result);
})

注:数据类型对照

Sequelize.STRING                      // VARCHAR(255)
Sequelize.STRING(1234)                // VARCHAR(1234)
Sequelize.STRING.BINARY               // VARCHAR BINARY
Sequelize.TEXT                        // TEXT
Sequelize.TEXT('tiny')                // TINYTEXT

Sequelize.INTEGER                     // INTEGER
Sequelize.BIGINT                      // BIGINT
Sequelize.BIGINT(11)                  // BIGINT(11)

Sequelize.FLOAT                       // FLOAT
Sequelize.FLOAT(11)                   // FLOAT(11)
Sequelize.FLOAT(11, 12)               // FLOAT(11,12)

Sequelize.REAL                        // REAL        PostgreSQL only.
Sequelize.REAL(11)                    // REAL(11)    PostgreSQL only.
Sequelize.REAL(11, 12)                // REAL(11,12) PostgreSQL only.

Sequelize.DOUBLE                      // DOUBLE
Sequelize.DOUBLE(11)                  // DOUBLE(11)
Sequelize.DOUBLE(11, 12)              // DOUBLE(11,12)

Sequelize.DECIMAL                     // DECIMAL
Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)

Sequelize.DATE                        // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
Sequelize.DATE(6)                     // DATETIME(6) for mysql 5.6.4+. Fractional seconds support with up to 6 digits of precision
Sequelize.DATEONLY                    // DATE without time.
Sequelize.BOOLEAN                     // TINYINT(1)

Sequelize.ENUM('value 1', 'value 2')  // An ENUM with allowed values 'value 1' and 'value 2'
Sequelize.ARRAY(Sequelize.TEXT)       // Defines an array. PostgreSQL only.
Sequelize.ARRAY(Sequelize.ENUM)       // Defines an array of ENUM. PostgreSQL only.

Sequelize.JSON                        // JSON column. PostgreSQL, SQLite and MySQL only.
Sequelize.JSONB                       // JSONB column. PostgreSQL only.

Sequelize.BLOB                        // BLOB (bytea for PostgreSQL)
Sequelize.BLOB('tiny')                // TINYBLOB (bytea for PostgreSQL. Other options are medium and long)

Sequelize.UUID                        // UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically)

Sequelize.RANGE(Sequelize.INTEGER)    // Defines int4range range. PostgreSQL only.
Sequelize.RANGE(Sequelize.BIGINT)     // Defined int8range range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DATE)       // Defines tstzrange range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DATEONLY)   // Defines daterange range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DECIMAL)    // Defines numrange range. PostgreSQL only.

Sequelize.ARRAY(Sequelize.RANGE(Sequelize.DATE)) // Defines array of tstzrange ranges. PostgreSQL only.

Sequelize.GEOMETRY                    // Spatial column.  PostgreSQL (with PostGIS) or MySQL only.
Sequelize.GEOMETRY('POINT')           // Spatial column with geometry type. PostgreSQL (with PostGIS) or MySQL only.
Sequelize.GEOMETRY('POINT', 4326)     // Spatial column with geometry type and SRID.  PostgreSQL (with PostGIS) or MySQL only.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容